﻿using System;
using Bricks.Data;
using NHibernate;

namespace Bricks.NHibernate.Data
{
    
    /// <summary>
    /// 
    /// </summary>
    public abstract class SessionFacadeBase : ContextFacadeBase<ISession>, ISessionFacade
    {

        /// <summary>
        /// 
        /// </summary>
        /// <param name="session"></param>
        protected SessionFacadeBase(ISession session) :
            base(session)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="action"></param>
        /// <returns></returns>
        public override TResult Transact<TResult>(Func<TResult> action)
        {
            return Execute<TResult>(session =>
            {
                if (session.Transaction.IsActive)
                {
                    return action.Invoke();
                }
                else
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        try
                        {
                            TResult result = action.Invoke();

                            transaction.Commit();

                            return result;
                        }
                        catch
                        {
                            transaction.Rollback();

                            throw;
                        }
                    }
                }
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity"></param>
        public override void Add<TEntity>(TEntity entity)
        {
            Execute(session => session.Save(entity));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity"></param>
        public override void Remove<TEntity>(TEntity entity)
        {
            Execute(session => session.Delete(entity));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity"></param>
        public override void Update<TEntity>(TEntity entity)
        {
            Execute(session => session.SaveOrUpdate(entity));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity"></param>
        public override void Merge<TEntity>(TEntity entity)
        {
            Execute(session => session.Merge(entity));
        }
    }
}
